package netty.rpc.framework.core.netty.transport.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import netty.rpc.framework.core.netty.transport.codec.Byte2RPCMessageDecoder;
import netty.rpc.framework.core.netty.transport.codec.RPCMessage2ByteEncoder;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

/**
 * RPCClient是客户端快速启动器，通过变量channel与服务端进行交互
 */
@Slf4j
public class NettyCilent {

    private Channel channel;

    private Bootstrap bootstrap = new Bootstrap();

    public NettyCilent() {
        try {
            init();
        } catch (InterruptedException e) {
            log.error("RPCClient客户端初始化失败!");
        }
    }

    private void init() throws InterruptedException {
        EventLoopGroup work = new NioEventLoopGroup();
        bootstrap.group(work);
        bootstrap.channel(NioSocketChannel.class);

        bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        bootstrap.handler(
                new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast(new IdleStateHandler(10,0,0, TimeUnit.SECONDS));
                        pipeline.addLast(new RPCMessage2ByteEncoder());
                        pipeline.addLast(new Byte2RPCMessageDecoder());

                        pipeline.addLast(new ClientHandler());

                    }
                }
        );

    }

    public Channel connect(InetSocketAddress address){
        ChannelFuture channelFuture = bootstrap.connect(address);
        channelFuture.addListener((ChannelFuture futureListener) -> {
            if (futureListener.isSuccess()) {
                log.info("RPCClient客户端连接成功!");

            } else {
                log.error("RPCClient客户端连接失败!");
            }

        });

        // 阻塞,直到连接完成
        try {
            channelFuture.sync();
        } catch (InterruptedException e) {
            log.error("RPCClient连接失败！");
        }
        NioSocketChannel channel = (NioSocketChannel) channelFuture.channel();
        this.channel = channel;
        return channel;
    }

    public Channel getChannel() {
        return channel;
    }
}
